package middlewares

import (
	"errors"
	_const "longmen/server/pkg/common/helper/const"
	utils2 "longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/common/services"
	"longmen/server/pkg/db/redis/cache"
	"strings"
	"sync"
	"time"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	"github.com/spf13/cast"
)

var skipVerifyFunc map[string]int

func InitSkipVerifyFunc() {
	skipVerifyFunc = make(map[string]int)
	skipVerifyFunc["/api/live/getLivePageData"] = 1
	skipVerifyFunc["/webapi/live/getLivePageData"] = 2
	skipVerifyFunc["/webapi/search"] = 3
	skipVerifyFunc["/api/search"] = 4
	skipVerifyFunc["/api/task/getTaskList"] = 5
	skipVerifyFunc["/webapi/task/getTaskList"] = 6
	skipVerifyFunc["/api/match/getMatch4Crawler"] = 7
	skipVerifyFunc["/webapi/match/getMatch4Crawler"] = 8
	skipVerifyFunc["/webapi/home/getHomeUserRecLive"] = 9
	skipVerifyFunc["/api/home/getHomeUserRecLive"] = 10
	skipVerifyFunc["/webapi/noble/getNobleById"] = 11
	skipVerifyFunc["/api/noble/getNobleById"] = 12
	skipVerifyFunc["/webapi/expert/getExpertPlan"] = 13
	skipVerifyFunc["/api/expert/getExpertPlan"] = 14
	skipVerifyFunc["/webapi/match/getMatchList"] = 15
	skipVerifyFunc["/api/match/getMatchList"] = 16
	skipVerifyFunc["/webapi/expert/getExpertList"] = 17
	skipVerifyFunc["/api/expert/getExpertList"] = 18
	skipVerifyFunc["/webapi/expert/getExpertById"] = 19
	skipVerifyFunc["/api/expert/getExpertById"] = 20
	skipVerifyFunc["/webapi/models_live/getMatchLiveList"] = 21
	skipVerifyFunc["/api/models_live/getMatchLiveList"] = 22
	skipVerifyFunc["/api/tencentIm/getUserSig"] = 23
	skipVerifyFunc["/api/gift/getGiftListNew"] = 24
	skipVerifyFunc["/webapi/gift/getGiftListNew"] = 25
	skipVerifyFunc["/api/checkin/getCheckinInfo"] = 26
	skipVerifyFunc["/webapi/checkin/getCheckinInfo"] = 27
	skipVerifyFunc["/api/lottery/getLottery"] = 28
	skipVerifyFunc["/webapi/lottery/getLottery"] = 29
	skipVerifyFunc["/api/lottery/getLotteryAwardsInfo"] = 30
	skipVerifyFunc["/webapi/lottery/getLotteryAwardsInfo"] = 31
	skipVerifyFunc["/api/lottery/getLotteryHistory"] = 32
	skipVerifyFunc["/webapi/lottery/getLotteryHistory"] = 33
	skipVerifyFunc["/api/privateChat/getRecord"] = 34
	skipVerifyFunc["/webapi/privateChat/getRecord"] = 35
	skipVerifyFunc["/api/privateChat/getRecordDetail"] = 36
	skipVerifyFunc["/webapi/privateChat/getRecordDetail"] = 37
	skipVerifyFunc["/api/privateChat/unreadMsg"] = 38
	skipVerifyFunc["/webapi/privateChat/unreadMsg"] = 39
	skipVerifyFunc["/api/privateChat/read"] = 40
	skipVerifyFunc["/webapi/privateChat/read"] = 41
	skipVerifyFunc["/api/groupChat/getChatList"] = 42
	skipVerifyFunc["/webapi/groupChat/getChatList"] = 43
	skipVerifyFunc["/api/match/getHotMatchCards4Crawler"] = 44
	skipVerifyFunc["/api/live/getMatchLiveList"] = 45
	skipVerifyFunc["/api/game/fruit_game_config"] = 46
	skipVerifyFunc["/api/live/anchor_detail"] = 47
	skipVerifyFunc["/webapi/game/fruit_game_config"] = 48
	skipVerifyFunc["/api/game/fruit_game_config"] = 49
	skipVerifyFunc["/api/sport/point_detail"] = 50
	skipVerifyFunc["/webapi/sport/point_detail"] = 51
}

var RequestLimit = newRequestLimitService(time.Second, 5000)

type BasicAuthConfig struct {
	BasicAuthSkipper middleware.Skipper
	*services.Service
}

func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			if RequestLimit.isAvailable() {
				RequestLimit.increase()
			} else {
				return utils2.BuildLoginTimeOut(c, errors.New("超过流量限制！！！！！！"))
			}
			if config.BasicAuthSkipper(c) {
				return next(c)
			}
			var token string
			var uid int
			token = utils2.GetCookie(c, "token") //此处设置cookie便于swagger调试,线上可删除
			uid = cast.ToInt(utils2.GetCookie(c, "uid"))
			authorization := strings.Split(c.Request().Header.Get("authorization"), ";")
			if len(authorization) >= 2 { //截取请求头中 token 和 uid
				tokenSlice := strings.Split(authorization[0], "=")
				uidSlice := strings.Split(authorization[1], "=")
				if len(tokenSlice) >= 2 && len(uidSlice) >= 2 {
					token = tokenSlice[1]
					uid = cast.ToInt(uidSlice[1])
				}
			}

			if _, ok := skipVerifyFunc[c.Path()]; ok {
				c.Set("uid", uid)
				return next(c)
			}

			if token == _const.TOKEN_KICKED_OUT {
				return utils2.BuildLoginTimeOut(c, errors.New("被管理员踢出"))
			}
			val, err := cache.GetUserTokenLuaAuth(uid, token)
			if err != nil {
				return utils2.BuildLoginTimeOut(c, err)
			}

			if val == 0 {
				return utils2.BuildLoginTimeOut(c, errors.New("登陆超时"))
			}
			c.Set("uid", uid)
			return next(c)
		}
	}
}

type requestLimitService struct {
	Interval time.Duration
	MaxCount int
	Lock     sync.Mutex
	ReqCount int
}

func newRequestLimitService(interval time.Duration, maxCnt int) *requestLimitService {
	reqLimit := &requestLimitService{
		Interval: interval,
		MaxCount: maxCnt,
	}
	go func() {
		ticker := time.NewTicker(interval)
		for {
			<-ticker.C
			reqLimit.Lock.Lock()
			reqLimit.ReqCount = 0
			reqLimit.Lock.Unlock()
		}
	}()

	return reqLimit
}

func (reqLimit *requestLimitService) increase() {
	reqLimit.Lock.Lock()
	defer reqLimit.Lock.Unlock()

	reqLimit.ReqCount += 1
}

func (reqLimit *requestLimitService) isAvailable() bool {
	reqLimit.Lock.Lock()
	defer reqLimit.Lock.Unlock()
	return reqLimit.ReqCount < reqLimit.MaxCount
}
